﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Windows.Input;
using Windows.Foundation;
using Windows.UI.Xaml.Markup;

namespace LayoutHelpers.BaseTypes
{
  [ContentProperty(Name = "TrueCommand")]
  public abstract class ConditionalLayoutRule<T> : ILayoutRule, ICommand, ILayoutEvaluator where T : ILayoutEvaluator, new()
  {
    virtual public T LayoutEvaluator { get; private set; }
    virtual public ICommand TrueCommand { get; set; }
    virtual public ICommand FalseCommand { get; set; }
    virtual public string DisplayName { get; set; }

    public ConditionalLayoutRule()
    {
      LayoutEvaluator = new T();
    }

    ILayoutEvaluator ILayoutRule.LayoutEvaluator
    {
      get { return this; }
    }

    ICommand ILayoutRule.Command
    {
      get { return this; }
    }

    bool? lastEvaluateResult;
    public bool Evaluate(Size availableSize)
    {
      if (TrueCommand == null && FalseCommand == null)
      {
        lastEvaluateResult = null;
        return false;
      }

      lastEvaluateResult = LayoutEvaluator.Evaluate(availableSize);

      if (TrueCommand != null)
      {
        if (FalseCommand != null)
          return true;
        else
          return lastEvaluateResult.Value;
      }
      else if (FalseCommand != null)
      {
        return !lastEvaluateResult.Value;
      }

      return false;
    }

    public bool CanExecute(object parameter)
    {
      if (lastEvaluateResult == null)
        return false;
      else if (lastEvaluateResult == true && TrueCommand != null)
        return TrueCommand.CanExecute(parameter);
      else if (FalseCommand != null)
        return FalseCommand.CanExecute(parameter);

      return false;
    }

    protected void RaiseCanExecuteChanged()
    {
      var handler = CanExecuteChanged;
      if (handler != null)
        CanExecuteChanged(this, EventArgs.Empty);
    }
    public event EventHandler CanExecuteChanged;

    public void Execute(object parameter)
    {
      if (lastEvaluateResult == null)
        return;
      else if (lastEvaluateResult == true && TrueCommand != null)
        TrueCommand.Execute(parameter);
      else if (FalseCommand != null)
        FalseCommand.Execute(parameter);
    }
  }
}
